#include <sstream>
#include <stdlib.h>
#include "common.h"

#include "regdword_editor.h"

Regdword_Editor::Regdword_Editor(const Glib::ustring & val_name, unsigned int val_data)
{
	last_base_ = HEX_BASE;
	std::stringstream num;
	num << std::hex;
	num << val_data;
	origin_data_ = num.str();
	set_size_request(350, 200);
	set_title("修改数值");
	
	Gtk::VBox* area = Gtk::Dialog::get_vbox();
	if (NULL != area) {
		area->set_spacing(10);
		Gtk::VBox *vbox1 = Gtk::manage(new Gtk::VBox());		
		area->pack_end(*vbox1);
		vbox1->pack_start(*Gtk::manage(new Gtk::Label(" 数值名称(Name):", Gtk::ALIGN_LEFT)), Gtk::PACK_EXPAND_PADDING);
		Gtk::Entry * name = Gtk::manage(new Gtk::Entry());
		if (NULL != name) {
			name->set_text(val_name);			
			name->property_editable() = false;
			vbox1->pack_start(*name, Gtk::PACK_EXPAND_PADDING);
		}
		Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox());	// 创建值输入区和基数选择区的水平分割
		vbox1->pack_start(*hbox);
		Gtk::VBox *vbox2 = Gtk::manage(new Gtk::VBox());	// data input area
		hbox->pack_start(*vbox2); //TODO: out of memory test will be add
		Gtk::Frame *frame = Gtk::manage(new Gtk::Frame());	// base number chooser area
		hbox->pack_start(*frame); //TODO: out of memory test will be add
		frame->set_label("基数(base)");
		Gtk::VBox *vbox_base_select = Gtk::manage(new Gtk::VBox());	// data input area
		frame->add(*vbox_base_select);
		Gtk::RadioButton::Group group;
		base_hex_ = new Gtk::RadioButton(group, "十六进制(Hex)");
		if (NULL != base_hex_) {
			vbox_base_select->pack_start(*Gtk::manage(base_hex_));
			base_hex_->signal_clicked().connect(sigc::mem_fun(*this,
				&Regdword_Editor::on_radio_button_clicked));
		}
		vbox_base_select->pack_start(*Gtk::manage(new Gtk::RadioButton(group, "十进制(Dec)")));
		vbox2->pack_start(*Gtk::manage(new Gtk::Label(" 数值数据(data):", Gtk::ALIGN_LEFT, Gtk::ALIGN_BOTTOM)), 
		Gtk::PACK_EXPAND_PADDING);
		edit_data_ = Gtk::manage(new Gtk::Entry());
		if (NULL != edit_data_) {
			edit_data_->set_max_length(8);
			edit_data_->set_text(origin_data_);
			vbox2->pack_start(*edit_data_, Gtk::PACK_EXPAND_PADDING);
			edit_data_->signal_changed().connect(sigc::mem_fun(*this, 
			&Regdword_Editor::on_text_activate)); 
		}
		show_all_children();
		set_focus(*edit_data_);
	}
	Gtk::Button * ok_btn = add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
	add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
	if (NULL != ok_btn) {
		ok_btn->set_flags(Gtk::CAN_DEFAULT);
		ok_btn->grab_default();
	}
}

Regdword_Editor::~Regdword_Editor()
{
}

void 
Regdword_Editor::on_text_activate()
{
	Glib::ustring text = edit_data_->get_text();
	if (base_hex_->get_active()) { // base hex
		for (unsigned i = 0; i < text.length(); ++i) {
			if (!((text[i] >= '0' && text[i] <= '9') || 
			(text[i] >= 'a' && text[i] <= 'f') ||
			(text[i] >= 'A' && text[i] <= 'F'))) {
				edit_data_->set_text(origin_data_);
				return;
			}
		}
	} else { // base dec
		for (unsigned i = 0; i < text.length(); ++i) {
			if (text[i] < '0' || text[i] > '9') {
				edit_data_->set_text(origin_data_);
				return;
			}
		}
	}

	origin_data_ = text;
}

void Regdword_Editor::on_radio_button_clicked()
{
	std::stringstream	result;
	if (base_hex_->get_active() && DEC_BASE == last_base_) {	// dec to hex
		result << std::hex;
		result << strtoul(edit_data_->get_text().c_str(), NULL, 10);
		edit_data_->set_max_length(8);
		edit_data_->set_text(result.str());
		last_base_ = HEX_BASE;
	} else if (!base_hex_->get_active() && HEX_BASE == last_base_) {	// hex to dec
		result << std::dec;
		result << strtoul(edit_data_->get_text().c_str(), NULL, 16);
		edit_data_->set_max_length(10);
		edit_data_->set_text(result.str());
		last_base_ = DEC_BASE;
	}
}

unsigned int
Regdword_Editor::get_result() const
{
	return strtoul(edit_data_->get_text().c_str(), NULL, 
	HEX_BASE == last_base_ ? 16 : 10);	
}

bool
Regdword_Editor::is_modify() const
{
	return true;
}
